/**
 * Copyright (c) 2018, 西安星沙网络科技-版权所有
 *
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.waleychain.exchange.service.impl.trade;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import cn.waleychain.exchange.core.cache.CacheConts;
import cn.waleychain.exchange.core.constant.DDIC;
import cn.waleychain.exchange.core.entity.NewPriceDTO;
import cn.waleychain.exchange.core.exec.CoinWalletSyncException;
import cn.waleychain.exchange.core.result.RetResultCode;
import cn.waleychain.exchange.core.utils.BigDecimalUtils;
import cn.waleychain.exchange.dao.DealOrderMapper;
import cn.waleychain.exchange.dao.EntrustOrderMapper;
import cn.waleychain.exchange.dao.TradeDataMapper;
import cn.waleychain.exchange.feign.MarketServiceFeign;
import cn.waleychain.exchange.model.DealOrder;
import cn.waleychain.exchange.model.EntrustOrder;
import cn.waleychain.exchange.model.Market;
import cn.waleychain.exchange.service.impl.BaseServiceImpl;
import cn.waleychain.exchange.service.trade.CacheDataService;

@Service
public class CacheDataServiceImpl extends BaseServiceImpl implements CacheDataService {

	@Autowired
	private MarketServiceFeign marketFeign;
	
	@Autowired
	private DealOrderMapper dealOrderMapper;
	
	@Autowired
	private EntrustOrderMapper entrustOrderMapper;
	
	@Autowired
	private TradeDataMapper tradeDataMapper;
	
	@Override
	public void resetTurnoverOrderList() throws Exception {
		// 获取所有市场对
		List<Market> list = marketFeign.fetchCacheMarketVaildList();
		if (list != null && list.size() > 0) {
			Iterator<Market> iter = list.iterator();
			while (iter.hasNext()) {
				Market market = iter.next();
				// 交易对ID
				long marketId = market.getMarketId();
				
				// 查询最新60条成交订单
				List<DealOrder> dealOrderList = dealOrderMapper.fetchDealOrderListLimit(marketId, DDIC.DealOrderStatus.TRADED.id, 60);
				
				this.setTurnoverOrder2Cache(marketId, dealOrderList);
			}
		}
		// 缓存最新成交价
		this.setNewPrice2Cache();
	}

	@Override
	public void resetNewestEntrustOrderList() throws Exception {
		
		int limit = 30;
		// 获取交易对
		List<Market> list = marketFeign.fetchCacheMarketVaildList();
		if (list != null && list.size() > 0) {
			Iterator<Market> iter = list.iterator();
			while (iter.hasNext()) {
				
				Market market = iter.next();
				long marketId = market.getMarketId();
				List<EntrustOrder> buyList = entrustOrderMapper.fetchNewEntrustOrderList(marketId, DDIC.TradeType.BUY.id, "priceDesc", limit);
				// 放入缓存
				this.setEntrustBuyOrder2Cache(marketId, buyList);
				
				List<EntrustOrder> sellList = entrustOrderMapper.fetchNewEntrustOrderList(marketId, DDIC.TradeType.SELL.id, "priceAsc", limit);
				// 放入缓存
				this.setEntrustSellOrder2Cache(marketId, sellList);
			}
		}
		
	}

	@Override
	public void setTurnoverOrder2Cache(long marketId, List<DealOrder> dealOrderList) throws Exception {
		
		boolean isLocked = false;
		try {
			
			isLocked = this.redisService.lock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_DEAL_ORDER_KEY, true);
			if (!isLocked) {
				throw new CoinWalletSyncException(RetResultCode.E13004);
			}
			
			this.setCacheNotExpi(CacheConts.NEWST_DEAL_ORDER_KEY, String.valueOf(marketId), dealOrderList);
			
		} catch (Exception var19) {
			throw var19;
		} finally {
			if (isLocked) {
				// 释放锁
				this.redisService.unlock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_DEAL_ORDER_KEY);
			}

		}
		
	}

	@Override
	public void setEntrustBuyOrder2Cache(long marketId, List<EntrustOrder> buyOrderList) throws Exception {
		
		boolean isLocked = false;
		try {
			
			isLocked = this.redisService.lock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_ENTRUST_BUY_ORDER_KEY, true);
			if (!isLocked) {
				throw new CoinWalletSyncException(RetResultCode.E13004);
			}
			
			this.setCacheNotExpi(CacheConts.NEWST_ENTRUST_BUY_ORDER_KEY, String.valueOf(marketId), buyOrderList);
			
		} catch (Exception var19) {
			throw var19;
		} finally {
			if (isLocked) {
				// 释放锁
				this.redisService.unlock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_ENTRUST_BUY_ORDER_KEY);
			}

		}
	}

	@Override
	public void setEntrustSellOrder2Cache(long marketId, List<EntrustOrder> sellOrderList) throws Exception {
		
		boolean isLocked = false;
		try {
			
			isLocked = this.redisService.lock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_ENTRUST_SELL_ORDER_KEY, true);
			if (!isLocked) {
				throw new CoinWalletSyncException(RetResultCode.E13004);
			}
			
			this.setCacheNotExpi(CacheConts.NEWST_ENTRUST_SELL_ORDER_KEY, String.valueOf(marketId), sellOrderList);
			
		} catch (Exception var19) {
			throw var19;
		} finally {
			if (isLocked) {
				// 释放锁
				this.redisService.unlock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_ENTRUST_SELL_ORDER_KEY);
			}

		}
	}

	/**
	 * 取最新交易单
	 * @param marketId
	 * @param dealOrderList
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public List<DealOrder> getTurnoverOrder2Cache(long marketId) throws Exception {
		
		return (List<DealOrder>) this.get(CacheConts.NEWST_DEAL_ORDER_KEY, String.valueOf(marketId));
	}
	
	/**
	 * 取最新的委托买单
	 * @param marketId
	 * @param buyOrderList
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public List<EntrustOrder> getEntrustBuyOrder2Cache(long marketId) throws Exception {
	
		return (List<EntrustOrder>) this.get(CacheConts.NEWST_ENTRUST_BUY_ORDER_KEY, String.valueOf(marketId));
	}
	
	/**
	 * 取最新的委托卖单
	 * @param marketId
	 * @param sellOrderList
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public List<EntrustOrder> getEntrustSellOrder2Cache(long marketId) throws Exception {
		
		return (List<EntrustOrder>) this.get(CacheConts.NEWST_ENTRUST_SELL_ORDER_KEY, String.valueOf(marketId));
	}
	
	@Override
	public void setNewPrice2Cache() throws Exception {
		
		boolean isLocked = false;
		try {
			
			isLocked = this.redisService.lock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_ENTRUST_SELL_ORDER_KEY, true);
			if (!isLocked) {
				throw new CoinWalletSyncException(RetResultCode.E13004);
			}
			
			List<NewPriceDTO> newPriceList = tradeDataMapper.fetchNewPrice();
			if (!CollectionUtils.isEmpty(newPriceList)) {
				for (NewPriceDTO newPriceDTO : newPriceList) {
					this.setCacheNotExpi(CacheConts.NEWST_PRICE_KEY, String.valueOf(newPriceDTO.getMarketId()), newPriceDTO);
				}
			}
			
		} catch (Exception var19) {
			throw var19;
		} finally {
			if (isLocked) {
				// 释放锁
				this.redisService.unlock(CacheConts.LOCK_STATIC_DATA, CacheConts.NEWST_ENTRUST_SELL_ORDER_KEY);
			}

		}
	}
	
	/**
	 * 获取最新价
	 * @throws Exception
	 */
	@Override
	public BigDecimal getNewPrice2Cache(long marketId) throws Exception {
		
		NewPriceDTO newPriceDTO = (NewPriceDTO) this.get(CacheConts.NEWST_PRICE_KEY, String.valueOf(marketId));
		if (newPriceDTO == null) {
			this.setNewPrice2Cache();
			newPriceDTO = (NewPriceDTO) this.get(CacheConts.NEWST_PRICE_KEY, String.valueOf(marketId));
		}
		return newPriceDTO == null ? BigDecimalUtils.genInitValue() : newPriceDTO.getPrice();
	}

	@Override
	public void setKLines2Cache(long marketId, Map<String, List<String>> kLines) throws Exception {
		
		boolean isLocked = false;
		try {
			
			isLocked = this.redisService.lock(CacheConts.LOCK_STATIC_DATA, CacheConts.K_LINE_DATA_KEY, true);
			if (!isLocked) {
				throw new CoinWalletSyncException(RetResultCode.E13004);
			}
			
			this.setCacheNotExpi(CacheConts.K_LINE_DATA_KEY, String.valueOf(marketId), kLines);
			
		} catch (Exception var19) {
			throw var19;
		} finally {
			if (isLocked) {
				// 释放锁
				this.redisService.unlock(CacheConts.LOCK_STATIC_DATA, CacheConts.K_LINE_DATA_KEY);
			}

		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, List<String>> getKLines2Cache(long marketId) throws Exception {

		Object obj = this.get(CacheConts.K_LINE_DATA_KEY, String.valueOf(marketId));
		
		return obj == null ? null : (Map<String, List<String>>) obj;
	}

}
